import { BaseGraph } from 'pml-graph'
/**
 * 特定业务定制类
 */
import itemMeta from '@/graph/item-box-config.js'
class GraphApi extends BaseGraph {
  constructor() {
    super()
  }
  init(graphContainer, enabled) {
    super.initGraph(graphContainer, enabled)
    // keep connected when mouse drag move
    this.graph.setDisconnectOnMove(false)
    this.graph.foldingEnabled = false
    const createSvgImage = function(w, h, data, coordWidth, coordHeight) {
      var tmp = unescape(encodeURIComponent(
        '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' +
                '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="' + w + 'px" height="' + h + 'px" ' +
                ((coordWidth != null && coordHeight != null) ? 'viewBox="0 0 ' + coordWidth + ' ' + coordHeight + '" ' : '') +
                'version="1.1">' + data + '</svg>'))

      return new mxImage('data:image/svg+xml;base64,' + ((window.btoa) ? btoa(tmp) : Base64.encode(tmp, true)), w, h)
    }
    const handleImage = createSvgImage(18, 18, '<circle cx="9" cy="9" r="5" stroke="#fff" fill="#29b6f2" stroke-width="1"/>')
    const fixedHandleImage = createSvgImage(18, 18, '<circle cx="9" cy="9" r="5" stroke="#fff" fill="#29b6f2" stroke-width="1"/><path d="m 7 7 L 11 11 M 7 11 L 11 7" stroke="#fff"/>')
    const terminalHandleImage = createSvgImage(18, 18, '<circle cx="9" cy="9" r="5" stroke="#fff" fill="#29b6f2" stroke-width="1"/><circle cx="9" cy="9" r="2" stroke="#fff" fill="transparent"/>')

    mxEdgeHandler.prototype.createHandleShape = function(index, virtual) {
      var source = index != null && index == 0
      var terminalState = this.state.getVisibleTerminalState(source)
      var c = (index != null && (index == 0 || index >= this.state.absolutePoints.length - 1 ||
                (this.constructor == mxElbowEdgeHandler && index == 2)))
        ? this.graph.getConnectionConstraint(this.state, terminalState, source) : null
      var pt = (c != null) ? this.graph.getConnectionPoint(this.state.getVisibleTerminalState(source), c) : null

      var img = (pt != null) ? fixedHandleImage : ((c != null && terminalState != null)
        ? terminalHandleImage : handleImage)
      if (img != null) {
        var shape = new mxImageShape(new mxRectangle(0, 0, img.width, img.height), img.src)

        // Allows HTML rendering of the images
        shape.preserveImageAspect = false

        return shape
      } else {
        var s = mxConstants.HANDLE_SIZE

        if (this.preferHtml) {
          s -= 1
        }
        return new mxRectangleShape(new mxRectangle(0, 0, s, s), mxConstants.HANDLE_FILLCOLOR, mxConstants.HANDLE_STROKECOLOR)
      }
    }
    var vertexHandlerCreateSizerShape = mxVertexHandler.prototype.createSizerShape
    mxVertexHandler.prototype.createSizerShape = function(bounds, index, fillColor) {
      if (index !== mxEvent.LABEL_HANDLE && index !== mxEvent.ROTATION_HANDLE) {
        this.handleImage = handleImage
      }

      return vertexHandlerCreateSizerShape.apply(this, arguments)
    }
    mxConnectionHandler.prototype.connectImage = new mxImage('mx/images/connector.gif', 16, 16)
    const style = new Object()
    style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_SWIMLANE
    style[mxConstants.STYLE_FONTCOLOR] = '#FFFFFF'
    style[mxConstants.STYLE_HORIZONTAL] = true
    style[mxConstants.STYLE_FILLCOLOR] = '#045D8A'
    style['rounded'] = 1
    style[mxConstants.STYLE_STROKECOLOR] = '#239AF7'
    style[mxConstants.STYLE_STROKEWIDTH] = 2
    style[mxConstants.STYLE_STARTSIZE] = 40
    style[mxConstants.STYLE_FILL_OPACITY] = 70
    this.graph.getStylesheet().putCellStyle('swimlane', style)
    this.registerImage()
    this.customGraphEvent()
  }

  update(shapeEle) {
    const itemMetaDataStr = shapeEle.getAttribute('objData')
    const itemMetaData = JSON.parse(itemMetaDataStr)
    var funct = (graph, evt, cell, x, y) => {
      if (!graph.isEnabled()) {
        return
      }
      var businessData = {
        type: itemMetaData.type,
        name: itemMetaData.value
      }
      var parent = graph.getDefaultParent()
      var model = this.model = graph.getModel()
      model.beginUpdate()
      var v1 = null
      if (cell && cell.type === 'cloud') {
        let rObj = null
        let xx = 0; let yy = 0
        const findP = (parent) => {
          if (parent.parent) findP(parent.parent)
          if (parent.type === 'cloud') {
            xx += parent.geometry.x
            yy += parent.geometry.y

            if (parent.mxObjectId === cell.mxObjectId) {
              rObj = parent
            }
          }
          return rObj
        }
        parent = findP(cell)
        v1 = graph.insertVertex(parent, null, itemMetaData.value, x - xx, y - yy, itemMetaData.width, itemMetaData.height, itemMetaData.style)
        graph.setCellStyles(mxConstants.STYLE_RESIZABLE, 0, [v1])
      } else if (itemMetaData.sharp == 'cloud') {
        v1 = graph.insertVertex(parent, null, itemMetaData.value, x, y, itemMetaData.width, itemMetaData.height, itemMetaData.style)

        if (v1 != null) {
          // this.addSubProcessOverlay(v1);
        }
      } else {
        v1 = graph.insertVertex(parent, null, itemMetaData.value, x, y, itemMetaData.width, itemMetaData.height, itemMetaData.style)
        graph.setCellStyles(mxConstants.STYLE_RESIZABLE, 0, [v1])
      }
      businessData.id = v1.id
      v1.type = itemMetaData.type
      this.setObjectData(v1.id, JSON.stringify(businessData))
      model.endUpdate()
      graph.setSelectionCell(v1)
    }
    var ds = mxUtils.makeDraggable(shapeEle, this.graph, funct)
    ds.setGuidesEnabled(true)
  }
  setXmlValue(xml) {
    super.setXmlValue(xml)
    this.addCellOverlays()
  }
  addCellOverlays() {
    const cells = this.getNodes()
    for (const cell of cells) {
      if (cell.type == 'cloud') {
        this.addCloudOverlay(cell)
      }
    }
  }
  addCloudOverlay(cell) {
    const graph = this.graph
    graph.removeCellOverlays(cell)
    // Creates a new overlay with an image
    var overlay = null
    if (cell.type == 'cloud') {
      const businessData = JSON.parse(cell.businessData || '{}')
      const cloudType = businessData.attribute ? businessData.attribute.cloudProvider : ''
      if (cloudType === '阿里云') {
        overlay = new mxCellOverlay(
          new mxImage('./img/graph/aliyun.png', 100, 30),
          null, 'center', 'top', new mxPoint(0, 20), 'pointer')
      } else if (cloudType === 'Openstack') {
        overlay = new mxCellOverlay(
          new mxImage('./img/graph/openstack.png', 100, 30),
          null, 'center', 'top', new mxPoint(0, 18), 'pointer')
      } else if (cloudType === '华为云') {
        overlay = new mxCellOverlay(
          new mxImage('./img/graph/huawei.png', 100, 35),
          null, 'center', 'top', new mxPoint(0, 20), 'pointer')
      } else if (cloudType == '腾讯云') {
        overlay = new mxCellOverlay(
          new mxImage('./img/graph/tencent.png', 100, 30),
          null, 'center', 'top', new mxPoint(0, 20), 'pointer')
      }
    }
    // Sets the overlay for the cell in the graph
    overlay && graph.addCellOverlay(cell, overlay)
  }
  registerImage() {
    for (const item of itemMeta) {
      if (item.type == 'cloud') continue
      const style = new Object()
      style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_IMAGE
      style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter
      style[mxConstants.STYLE_IMAGE] = item.icon
      style[mxConstants.STYLE_FONTCOLOR] = '#FFFFFF'
      style[mxConstants.STYLE_VERTICAL_ALIGN] = 'bottom'
      style[mxConstants.STYLE_SPACING] = '-16'
      this.graph.getStylesheet().putCellStyle(item.style, style)
    }
  }
  customGraphEvent() {
    const graph = this.graph
    // graph.model.addListener(mxEvent.CHANGE, function(sender, evt) {
    //     /**
    //      * 画图任何变动，增加图元、移动图元、连线等，都会触发
    //      */
    //     console.log("change")
    // });

    graph.addListener(mxEvent.REFRESH, function() {
      /**
                   *  元数据变化时，点击确定后触发
                   */
      console.log('graph is refresh')
    })

    // graph.addListener(mxEvent.FOLD_CELLS, (sender, evt) => {
    //     let cells = evt.getProperty("cells");
    //     for (var i = 0; i < cells.length; i++) {
    //         var geo = graph.model.getGeometry(cells[i]);
    //         if (geo.alternateBounds != null) {
    //             if (cells[i].isCollapsed()) {
    //                 geo.width = geo.alternateBounds.width - 450;
    //                 graph.setCellsResizable(false)
    //                 //graph.setCellStyles(mxConstants.STYLE_RESIZABLE, 0, cells)
    //             } else {
    //                 geo.width = geo.alternateBounds.width + 450;
    //                 //graph.setCellStyles(mxConstants.STYLE_RESIZABLE, 1, cells)
    //                 graph.setCellsResizable(true)
    //             }
    //         }
    //     }
    //     mxEvent.consume(evt, true, true)
    // })
    // this.addZoomListener();
  }
  getGraphMeta() {
    const metaData = this.getGraphMetaDataByParent()
    const nodes = metaData.nodes
    for (const node of nodes) {
      const cell = this.graph.model.getCell(node.id)
      if (cell.type == 'cloud') {
        node.nodes = this.getGraphMetaDataByParent(cell).nodes
        node.edges = this.getGraphMetaDataByParent(cell).edges
      }
    }
    return metaData
  }
}

export default GraphApi
